/*
 * @Author: jack_yang98 1246900429@qq.com
 * @Date: 2024-08-04 14:04:43
 * @LastEditors: jack_yang98 1246900429@qq.com
 * @LastEditTime: 2024-08-04 15:55:03
 * @FilePath: /gateway/app/app_message.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "app_message.h"
#include "string.h"
#include "stdlib.h"
#include "thirdparty/cJSON/cJSON.h"
#include "thirdparty/log/log.h"

// 将二进制数据转换为字符串, 调用者需要负责释放str
static char *bin_to_str(unsigned char *binary, int len)
{
    char *hex_str = malloc(len * 2 + 1);
    if (!hex_str)
    {
        log_warn("Not enough memory");
        return NULL;
    }

    for (int i = 0; i < len; i++)
    {
        sprintf(hex_str + i * 2, "%02X", binary[i]);
    }
    hex_str[len * 2] = '\0';
    return hex_str;
}

// 将字符串转化为二进制数据，返回实际转化的长度
static int str_to_bin(char *hex_str, unsigned char *binary, int len)
{
    if (strlen(hex_str) % 2 != 0)
    {
        log_warn("Hex string is not valid");
        return -1;
    }
    if (len < (int)(strlen(hex_str) / 2))
    {
        log_warn("Buffer len is not enough");
        return -1;
    }
    len = strlen(hex_str) / 2;
    for (int i = 0; i < len; i++)
    {
        // 现在需要转化的字节有两个，分别是hex_str[i*2]和hex_str[i*2+1]
        char high = hex_str[i * 2];
        char low = hex_str[i * 2 + 1];

        // 首先处理高位
        if (high <= '9' && high >= '0')
        {
            binary[i] = high - '0';
        }
        else if (high >= 'a' && high <= 'f')
        {
            binary[i] = high - 'a' + 10;
        }
        else if (high >= 'A' && high <= 'F')
        {
            binary[i] = high - 'A' + 10;
        }
        binary[i] <<= 4;

        // 再处理低位
        if (low <= '9' && low >= '0')
        {
            binary[i] |= low - '0';
        }
        else if (low >= 'a' && low <= 'f')
        {
            binary[i] |= low - 'a' + 10;
        }
        else if (low >= 'A' && low <= 'F')
        {
            binary[i] |= low - 'A' + 10;
        }
    }
    return len;
}
int App_message_initByBinary(Message *message,unsigned char *binary, int len)
{
    // 1.初始化消息
    memset(message, 0, sizeof(Message));

    // 2.获取连接类型
    memcpy(&message->connection_type, binary, 1);

    // 3.获取id长度和数据长度
    memcpy(&message->id_len, binary + 1, 1);
    memcpy(&message->data_len, binary + 2, 1);

    // 数据总共的长度
    int total_len = 3 + message->id_len + message->data_len;
    if (total_len != len)
    {
        log_error("数据长度有误 %d", total_len);
        return -1;
    }

    message->payload = malloc(total_len - 3);
    if (message->payload == NULL)
    {
        log_error("内存分配失败");
        App_message_free(message);
        return -1;
    }

    memcpy(message->payload, binary + 3, total_len - 3);

    log_debug("初始化为二进制成功");
    return 0;
}

int App_message_initByJson(Message *message, char *json_str, int len)
{
    // 1. 使用cJSON解析字符串
    cJSON *json_object = cJSON_ParseWithLength(json_str, len);
    if (json_object == NULL)
    {
        log_error("cJSON_ParseWithLength失败");
        return -1;
    }
    // 2. 获取数据
    message->connection_type = cJSON_GetObjectItem(json_object, "connection_type")->valueint;
    // 2.1读取id和data的长度
    cJSON *id = cJSON_GetObjectItem(json_object, "id");
    if (strlen(id->valuestring) % 2 != 0)
    {
        log_error("消息无效");
        cJSON_Delete(json_object); // 释放内存 很重要
        return -1;
    }
    message->id_len = strlen(id->valuestring) / 2;

    cJSON *data = cJSON_GetObjectItem(json_object, "data");
    if (strlen(data->valuestring) % 2 != 0)
    {
        log_error("消息无效");
        cJSON_Delete(json_object); // 释放内存 很重要
        return -1;
    }
    message->data_len = strlen(data->valuestring) / 2;

    message->payload = malloc(message->data_len + message->id_len);
    if (message->payload == NULL)
    {
        log_error("内存分配失败");
        cJSON_Delete(json_object); // 释放内存 很重要
        return -1;
    }

    if (str_to_bin(id->valuestring, message->payload, message->id_len) < 0)
    {
        log_warn("转换失败");
        cJSON_Delete(json_object); // 释放内存 很重要
        free(message->payload);
        return -1;
    }
    if (str_to_bin(data->valuestring, message->payload + message->id_len, message->data_len) < 0)
    {
        log_warn("转换失败");
        cJSON_Delete(json_object); // 释放内存 很重要
        free(message->payload);
        return -1;
    }

    cJSON_Delete(json_object); // 释放内存 很重要
    log_debug("初始化为JSON成功");
    return 0;
}

int App_message_saveBinary(Message *message,unsigned char *binary, int len)
{
    // 将来保存二进制需要的长度为 3个字节元数据和 id_len + data_len长度的数据
    int total_len = 3 + message->id_len + message->data_len;
    if (total_len > len)
    {
        log_error("内存不足");
        return -1;
    }
    binary[0] = message->connection_type;
    binary[1] = message->id_len;
    binary[2] = message->data_len;
    memcpy(binary + 3, message->payload, total_len - 3);

    log_debug("保存二进制数据成功");
    return total_len;
}

int App_message_saveJson(Message *message, char *json_str, int len)
{
    // 首先生成Json Object
    cJSON *json_object = cJSON_CreateObject();

    // 添加字段
    cJSON_AddNumberToObject(json_object, "connection_type", message->connection_type);
    cJSON_AddStringToObject(json_object, "id", bin_to_str(message->payload, message->id_len));
    cJSON_AddStringToObject(json_object, "data", bin_to_str(message->payload + message->id_len, message->data_len));

    // 打印json字符串
    char *str = cJSON_PrintUnformatted(json_object);
    if (len < (int)(strlen(str) + 1))
    {
        log_warn("Buffer not enough for message");
        return -1;
    }
    strcpy(json_str, str);

    cJSON_free(str);
    cJSON_Delete(json_object);

    log_debug("保存JSON字符串成功");
    return 0;
}

void App_message_free(Message *message)
{
    if (message->payload)
    {
        free(message->payload);
        message->payload = NULL;
    }
}
